/*     */ package com.zimbra.cs.service;
/*     */ 
/*     */ import com.google.common.base.Strings;
/*     */ import com.zimbra.common.account.Key.ServerBy;
/*     */ import com.zimbra.common.httpclient.HttpClientUtil;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.mime.ContentDisposition;
/*     */ import com.zimbra.common.mime.ContentType;
/*     */ import com.zimbra.common.mime.MimeDetect;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.service.ServiceException.Argument;
/*     */ import com.zimbra.common.service.ServiceException.Argument.Type;
/*     */ import com.zimbra.common.service.ServiceException.InternalArgument;
/*     */ import com.zimbra.common.soap.Element.JSONElement;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.FileUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LogFactory;
/*     */ import com.zimbra.common.util.MapUtil;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraHttpConnectionManager;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AuthToken;
/*     */ import com.zimbra.cs.account.Config;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.Server;
/*     */ import com.zimbra.cs.ldap.LdapUtil;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.servlet.ZimbraServlet;
/*     */ import com.zimbra.cs.servlet.util.CsrfUtil;
/*     */ import com.zimbra.cs.store.BlobInputStream;
/*     */ import com.zimbra.cs.util.AccountUtil;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.io.File;
/*     */ import java.io.FileFilter;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.PrintWriter;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Arrays;
/*     */ import java.util.Collection;
/*     */ import java.util.Collections;
/*     */ import java.util.Date;
/*     */ import java.util.HashMap;
/*     */ import java.util.Iterator;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Timer;
/*     */ import java.util.TimerTask;
/*     */ import java.util.regex.Matcher;
/*     */ import java.util.regex.Pattern;
/*     */ import javax.mail.util.SharedByteArrayInputStream;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ import org.apache.commons.fileupload.FileItem;
/*     */ import org.apache.commons.fileupload.FileItemFactory;
/*     */ import org.apache.commons.fileupload.FileUploadBase.InvalidContentTypeException;
/*     */ import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
/*     */ import org.apache.commons.fileupload.FileUploadException;
/*     */ import org.apache.commons.fileupload.disk.DiskFileItem;
/*     */ import org.apache.commons.fileupload.disk.DiskFileItemFactory;
/*     */ import org.apache.commons.fileupload.servlet.ServletFileUpload;
/*     */ import org.apache.commons.httpclient.Header;
/*     */ import org.apache.commons.httpclient.HttpClient;
/*     */ import org.apache.commons.httpclient.HttpException;
/*     */ import org.apache.commons.httpclient.methods.GetMethod;
/*     */ import org.apache.commons.lang.StringEscapeUtils;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class FileUploadServlet
/*     */   extends ZimbraServlet
/*     */ {
/*     */   private static final long serialVersionUID = -3156986245375108467L;
/*     */   protected static final String PARAM_LIMIT_BY_FILE_UPLOAD_MAX_SIZE = "lbfums";
/*     */   protected static final String PARAM_CSRF_TOKEN = "csrfToken";
/*     */   private final Pattern ALLOWED_REQUESTID_CHARS;
/*     */   public static final String UPLOAD_DELIMITER = ",";
/*     */   private static final String UPLOAD_PART_DELIMITER = ":";
/*     */   private static String sUploadDir;
/*     */   
/*     */   public FileUploadServlet()
/*     */   {
/* 104 */     this.ALLOWED_REQUESTID_CHARS = Pattern.compile("^[a-zA-Z0-9_.-]+$");
/*     */   }
/*     */   
/*     */ 
/*     */   public static final class Upload
/*     */   {
/*     */     final String accountId;
/*     */     
/*     */     String contentType;
/*     */     
/*     */     final String uuid;
/*     */     
/*     */     final String name;
/*     */     
/*     */     final FileItem file;
/*     */     long time;
/* 120 */     boolean deleted = false;
/*     */     BlobInputStream blobInputStream;
/*     */     
/*     */     Upload(String acctId, FileItem attachment) throws ServiceException {
/* 124 */       this(acctId, attachment, attachment.getName());
/*     */     }
/*     */     
/*     */     Upload(String acctId, FileItem attachment, String filename) throws ServiceException {
/* 128 */       assert (attachment != null);
/*     */       
/*     */ 
/* 131 */       String localServer = Provisioning.getInstance().getLocalServer().getId();
/* 132 */       this.accountId = acctId;
/* 133 */       this.time = System.currentTimeMillis();
/* 134 */       this.uuid = (localServer + ":" + LdapUtil.generateUUID());
/* 135 */       this.name = FileUtil.trimFilename(filename);
/* 136 */       this.file = attachment;
/* 137 */       if (this.file == null) {
/* 138 */         this.contentType = "text/plain";
/*     */ 
/*     */ 
/*     */ 
/*     */       }
/*     */       else
/*     */       {
/*     */ 
/*     */ 
/* 147 */         this.contentType = MimeDetect.getMimeDetect().detect(this.name);
/*     */         
/*     */ 
/* 150 */         if ((this.contentType == null) && (this.file.getContentType() != null) && 
/* 151 */           (this.file.getContentType().equals("text/xml"))) {
/* 152 */           this.contentType = this.file.getContentType();
/*     */         }
/*     */         
/*     */ 
/* 156 */         if (this.contentType == null) {
/*     */           try {
/* 158 */             this.contentType = MimeDetect.getMimeDetect().detect(this.file.getInputStream());
/*     */           } catch (Exception e) {
/* 160 */             this.contentType = null;
/*     */           }
/*     */         }
/*     */         
/*     */ 
/* 165 */         if ((this.contentType == null) || (this.contentType.equals("application/octet-stream"))) {
/* 166 */           this.contentType = this.file.getContentType();
/*     */         }
/*     */         
/*     */ 
/* 170 */         if (this.contentType == null)
/* 171 */           this.contentType = this.file.getContentType();
/* 172 */         if (this.contentType == null)
/* 173 */           this.contentType = "application/octet-stream";
/*     */       }
/*     */     }
/*     */     
/* 177 */     public String getName() { return this.name; }
/* 178 */     public String getId() { return this.uuid; }
/* 179 */     public String getContentType() { return this.contentType; }
/* 180 */     public long getSize() { return this.file == null ? 0L : this.file.getSize(); }
/* 181 */     public BlobInputStream getBlobInputStream() { return this.blobInputStream; }
/*     */     
/*     */     public InputStream getInputStream() throws IOException {
/* 184 */       if (wasDeleted()) {
/* 185 */         throw new IOException("Cannot get content for upload " + this.uuid + " because it was deleted.");
/*     */       }
/* 187 */       if (this.file == null) {
/* 188 */         return new SharedByteArrayInputStream(new byte[0]);
/*     */       }
/* 190 */       if ((!this.file.isInMemory()) && ((this.file instanceof DiskFileItem)))
/*     */       {
/*     */ 
/* 193 */         File f = ((DiskFileItem)this.file).getStoreLocation();
/* 194 */         this.blobInputStream = new BlobInputStream(f, f.length());
/* 195 */         return this.blobInputStream;
/*     */       }
/* 197 */       return this.file.getInputStream();
/*     */     }
/*     */     
/*     */ 
/* 201 */     boolean accessedAfter(long checkpoint) { return this.time > checkpoint; }
/*     */     
/*     */     void purge() {
/* 204 */       if (this.file != null) {
/* 205 */         FileUploadServlet.mLog.debug("Deleting from disk: id=%s, %s", new Object[] { this.uuid, this.file });
/* 206 */         this.file.delete();
/*     */       }
/* 208 */       if (this.blobInputStream != null) {
/* 209 */         this.blobInputStream.closeFile();
/*     */       }
/*     */     }
/*     */     
/*     */     synchronized void markDeleted() {
/* 214 */       this.deleted = true;
/*     */     }
/*     */     
/*     */     public synchronized boolean wasDeleted() {
/* 218 */       return this.deleted;
/*     */     }
/*     */     
/*     */     public String toString() {
/* 222 */       return "Upload: { accountId=" + this.accountId + ", time=" + new Date(this.time) + ", size=" + getSize() + ", uploadId=" + this.uuid + ", name=" + this.name + ", path=" + FileUploadServlet.getStoreLocation(this.file) + " }";
/*     */     }
/*     */   }
/*     */   
/*     */ 
/* 227 */   static HashMap<String, Upload> mPending = new HashMap(100);
/* 228 */   static Map<String, String> mProxiedUploadIds = MapUtil.newLruMap(100);
/* 229 */   static Log mLog = LogFactory.getLog(FileUploadServlet.class);
/*     */   
/*     */   static final long DEFAULT_MAX_SIZE = 10485760L;
/*     */   
/*     */   static final long UPLOAD_TIMEOUT_MSEC = 900000L;
/*     */   private static final long REAPER_INTERVAL_MSEC = 60000L;
/*     */   
/*     */   static String getUploadServerId(String uploadId)
/*     */     throws ServiceException
/*     */   {
/* 239 */     String[] parts = null;
/* 240 */     if ((uploadId == null) || ((parts = uploadId.split(":")).length != 2))
/* 241 */       throw ServiceException.INVALID_REQUEST("invalid upload ID: " + uploadId, null);
/* 242 */     return parts[0];
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   static boolean isLocalUpload(String uploadId)
/*     */     throws ServiceException
/*     */   {
/* 251 */     String serverId = getUploadServerId(uploadId);
/* 252 */     return Provisioning.getInstance().getLocalServer().getId().equals(serverId);
/*     */   }
/*     */   
/*     */   public static Upload fetchUpload(String accountId, String uploadId, AuthToken authtoken) throws ServiceException {
/* 256 */     mLog.debug("Fetching upload %s for account %s", new Object[] { uploadId, accountId });
/* 257 */     String context = "accountId=" + accountId + ", uploadId=" + uploadId;
/* 258 */     if ((accountId == null) || (uploadId == null)) {
/* 259 */       throw ServiceException.FAILURE("fetchUploads(): missing parameter: " + context, null);
/*     */     }
/*     */     
/* 262 */     if (!isLocalUpload(uploadId)) {
/* 263 */       return fetchRemoteUpload(accountId, uploadId, authtoken);
/*     */     }
/*     */     
/* 266 */     synchronized (mPending) {
/* 267 */       Upload up = (Upload)mPending.get(uploadId);
/* 268 */       if (up == null) {
/* 269 */         mLog.warn("upload not found: " + context);
/* 270 */         throw MailServiceException.NO_SUCH_UPLOAD(uploadId);
/*     */       }
/* 272 */       if (!accountId.equals(up.accountId)) {
/* 273 */         mLog.warn("mismatched accountId for upload: " + up + "; expected: " + context);
/* 274 */         throw MailServiceException.NO_SUCH_UPLOAD(uploadId);
/*     */       }
/* 276 */       up.time = System.currentTimeMillis();
/* 277 */       mLog.debug("fetchUpload() returning %s", new Object[] { up });
/* 278 */       return up;
/*     */     }
/*     */   }
/*     */   
/*     */   private static Upload fetchRemoteUpload(String accountId, String uploadId, AuthToken authtoken) throws ServiceException
/*     */   {
/* 284 */     String localUploadId = null;
/* 285 */     synchronized (mProxiedUploadIds) {
/* 286 */       localUploadId = (String)mProxiedUploadIds.get(uploadId);
/*     */     }
/* 288 */     if (localUploadId != null) {
/* 289 */       synchronized (mPending) {
/* 290 */         Upload up = (Upload)mPending.get(localUploadId);
/* 291 */         if (up != null) {
/* 292 */           return up;
/*     */         }
/*     */       }
/*     */     }
/* 296 */     Server server = Provisioning.getInstance().get(Key.ServerBy.id, getUploadServerId(uploadId));
/* 297 */     String url = AccountUtil.getBaseUri(server);
/* 298 */     if (url == null)
/* 299 */       return null;
/* 300 */     String hostname = server.getServiceHostname();
/* 301 */     url = url + "/service/content/proxy?aid=" + uploadId + '&' + "expunge" + "=true";
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 306 */     HttpClient client = ZimbraHttpConnectionManager.getInternalHttpConnMgr().newHttpClient();
/* 307 */     GetMethod get = new GetMethod(url);
/* 308 */     authtoken.encode(client, get, false, hostname);
/*     */     try
/*     */     {
/* 311 */       int statusCode = HttpClientUtil.executeMethod(client, get);
/* 312 */       if (statusCode != 200) {
/* 313 */         return null;
/*     */       }
/*     */       
/* 316 */       Header ctHeader = get.getResponseHeader("Content-Type");
/* 317 */       String contentType = ctHeader == null ? "text/plain" : ctHeader.getValue();
/* 318 */       Header cdispHeader = get.getResponseHeader("Content-Disposition");
/* 319 */       String filename = cdispHeader == null ? "unknown" : new ContentDisposition(cdispHeader.getValue()).getParameter("filename");
/*     */       
/*     */ 
/* 322 */       Upload up = saveUpload(get.getResponseBodyAsStream(), filename, contentType, accountId);
/* 323 */       synchronized (mProxiedUploadIds) {
/* 324 */         mProxiedUploadIds.put(uploadId, up.uuid);
/*     */       }
/* 326 */       return up;
/*     */     } catch (HttpException e) {
/* 328 */       throw ServiceException.PROXY_ERROR(e, url);
/*     */     } catch (IOException e) {
/* 330 */       throw ServiceException.RESOURCE_UNREACHABLE("can't fetch remote upload", e, new ServiceException.Argument[] { new ServiceException.InternalArgument("url", url, ServiceException.Argument.Type.STR) });
/*     */     } finally {
/* 332 */       get.releaseConnection();
/*     */     }
/*     */   }
/*     */   
/*     */   public static Upload saveUpload(InputStream is, String filename, String contentType, String accountId, boolean limitByFileUploadMaxSize) throws ServiceException, IOException {
/* 337 */     return saveUpload(is, filename, contentType, accountId, getFileUploadMaxSize(limitByFileUploadMaxSize));
/*     */   }
/*     */   
/*     */   /* Error */
/*     */   public static Upload saveUpload(InputStream is, String filename, String contentType, String accountId, long limit)
/*     */     throws ServiceException, IOException
/*     */   {
/*     */     // Byte code:
/*     */     //   0: aconst_null
/*     */     //   1: astore 6
/*     */     //   3: iconst_0
/*     */     //   4: istore 7
/*     */     //   6: lload 4
/*     */     //   8: invokestatic 85	com/zimbra/cs/service/FileUploadServlet:getUploader	(J)Lorg/apache/commons/fileupload/servlet/ServletFileUpload;
/*     */     //   11: astore 8
/*     */     //   13: aload 8
/*     */     //   15: invokevirtual 86	org/apache/commons/fileupload/servlet/ServletFileUpload:getSizeMax	()J
/*     */     //   18: lstore 9
/*     */     //   20: aload 8
/*     */     //   22: invokevirtual 87	org/apache/commons/fileupload/servlet/ServletFileUpload:getFileItemFactory	()Lorg/apache/commons/fileupload/FileItemFactory;
/*     */     //   25: ldc 88
/*     */     //   27: aload_2
/*     */     //   28: iconst_0
/*     */     //   29: aload_1
/*     */     //   30: invokeinterface 89 5 0
/*     */     //   35: astore 6
/*     */     //   37: aload_0
/*     */     //   38: iconst_1
/*     */     //   39: aload 6
/*     */     //   41: invokeinterface 90 1 0
/*     */     //   46: iconst_1
/*     */     //   47: lload 9
/*     */     //   49: lconst_0
/*     */     //   50: lcmp
/*     */     //   51: ifge +8 -> 59
/*     */     //   54: lload 9
/*     */     //   56: goto +7 -> 63
/*     */     //   59: lload 9
/*     */     //   61: lconst_1
/*     */     //   62: ladd
/*     */     //   63: invokestatic 91	com/zimbra/common/util/ByteUtil:copy	(Ljava/io/InputStream;ZLjava/io/OutputStream;ZJ)J
/*     */     //   66: lstore 11
/*     */     //   68: aload 8
/*     */     //   70: invokevirtual 86	org/apache/commons/fileupload/servlet/ServletFileUpload:getSizeMax	()J
/*     */     //   73: lconst_0
/*     */     //   74: lcmp
/*     */     //   75: iflt +55 -> 130
/*     */     //   78: lload 11
/*     */     //   80: aload 8
/*     */     //   82: invokevirtual 86	org/apache/commons/fileupload/servlet/ServletFileUpload:getSizeMax	()J
/*     */     //   85: lcmp
/*     */     //   86: ifle +44 -> 130
/*     */     //   89: getstatic 18	com/zimbra/cs/service/FileUploadServlet:mLog	Lcom/zimbra/common/util/Log;
/*     */     //   92: new 7	java/lang/StringBuilder
/*     */     //   95: dup
/*     */     //   96: invokespecial 8	java/lang/StringBuilder:<init>	()V
/*     */     //   99: ldc 92
/*     */     //   101: invokevirtual 10	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
/*     */     //   104: aload 8
/*     */     //   106: invokevirtual 86	org/apache/commons/fileupload/servlet/ServletFileUpload:getSizeMax	()J
/*     */     //   109: invokevirtual 93	java/lang/StringBuilder:append	(J)Ljava/lang/StringBuilder;
/*     */     //   112: ldc 94
/*     */     //   114: invokevirtual 10	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
/*     */     //   117: invokevirtual 11	java/lang/StringBuilder:toString	()Ljava/lang/String;
/*     */     //   120: invokevirtual 95	com/zimbra/common/util/Log:info	(Ljava/lang/Object;)V
/*     */     //   123: aload_1
/*     */     //   124: ldc 96
/*     */     //   126: invokestatic 97	com/zimbra/cs/mailbox/MailServiceException:UPLOAD_TOO_LARGE	(Ljava/lang/String;Ljava/lang/String;)Lcom/zimbra/cs/mailbox/MailServiceException;
/*     */     //   129: athrow
/*     */     //   130: new 30	com/zimbra/cs/service/FileUploadServlet$Upload
/*     */     //   133: dup
/*     */     //   134: aload_3
/*     */     //   135: aload 6
/*     */     //   137: invokespecial 98	com/zimbra/cs/service/FileUploadServlet$Upload:<init>	(Ljava/lang/String;Lorg/apache/commons/fileupload/FileItem;)V
/*     */     //   140: astore 13
/*     */     //   142: getstatic 18	com/zimbra/cs/service/FileUploadServlet:mLog	Lcom/zimbra/common/util/Log;
/*     */     //   145: ldc 99
/*     */     //   147: iconst_1
/*     */     //   148: anewarray 20	java/lang/Object
/*     */     //   151: dup
/*     */     //   152: iconst_0
/*     */     //   153: aload 13
/*     */     //   155: aastore
/*     */     //   156: invokevirtual 100	com/zimbra/common/util/Log:info	(Ljava/lang/String;[Ljava/lang/Object;)V
/*     */     //   159: getstatic 28	com/zimbra/cs/service/FileUploadServlet:mPending	Ljava/util/HashMap;
/*     */     //   162: dup
/*     */     //   163: astore 14
/*     */     //   165: monitorenter
/*     */     //   166: getstatic 28	com/zimbra/cs/service/FileUploadServlet:mPending	Ljava/util/HashMap;
/*     */     //   169: aload 13
/*     */     //   171: getfield 71	com/zimbra/cs/service/FileUploadServlet$Upload:uuid	Ljava/lang/String;
/*     */     //   174: aload 13
/*     */     //   176: invokevirtual 101	java/util/HashMap:put	(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
/*     */     //   179: pop
/*     */     //   180: aload 14
/*     */     //   182: monitorexit
/*     */     //   183: goto +11 -> 194
/*     */     //   186: astore 15
/*     */     //   188: aload 14
/*     */     //   190: monitorexit
/*     */     //   191: aload 15
/*     */     //   193: athrow
/*     */     //   194: iconst_1
/*     */     //   195: istore 7
/*     */     //   197: aload 13
/*     */     //   199: astore 14
/*     */     //   201: iload 7
/*     */     //   203: ifne +32 -> 235
/*     */     //   206: aload 6
/*     */     //   208: ifnull +27 -> 235
/*     */     //   211: getstatic 18	com/zimbra/cs/service/FileUploadServlet:mLog	Lcom/zimbra/common/util/Log;
/*     */     //   214: ldc 102
/*     */     //   216: iconst_1
/*     */     //   217: anewarray 20	java/lang/Object
/*     */     //   220: dup
/*     */     //   221: iconst_0
/*     */     //   222: aload 6
/*     */     //   224: aastore
/*     */     //   225: invokevirtual 21	com/zimbra/common/util/Log:debug	(Ljava/lang/String;[Ljava/lang/Object;)V
/*     */     //   228: aload 6
/*     */     //   230: invokeinterface 103 1 0
/*     */     //   235: aload 14
/*     */     //   237: areturn
/*     */     //   238: astore 16
/*     */     //   240: iload 7
/*     */     //   242: ifne +32 -> 274
/*     */     //   245: aload 6
/*     */     //   247: ifnull +27 -> 274
/*     */     //   250: getstatic 18	com/zimbra/cs/service/FileUploadServlet:mLog	Lcom/zimbra/common/util/Log;
/*     */     //   253: ldc 102
/*     */     //   255: iconst_1
/*     */     //   256: anewarray 20	java/lang/Object
/*     */     //   259: dup
/*     */     //   260: iconst_0
/*     */     //   261: aload 6
/*     */     //   263: aastore
/*     */     //   264: invokevirtual 21	com/zimbra/common/util/Log:debug	(Ljava/lang/String;[Ljava/lang/Object;)V
/*     */     //   267: aload 6
/*     */     //   269: invokeinterface 103 1 0
/*     */     //   274: aload 16
/*     */     //   276: athrow
/*     */     // Line number table:
/*     */     //   Java source line #341	-> byte code offset #0
/*     */     //   Java source line #342	-> byte code offset #3
/*     */     //   Java source line #345	-> byte code offset #6
/*     */     //   Java source line #346	-> byte code offset #13
/*     */     //   Java source line #347	-> byte code offset #20
/*     */     //   Java source line #349	-> byte code offset #37
/*     */     //   Java source line #350	-> byte code offset #68
/*     */     //   Java source line #351	-> byte code offset #89
/*     */     //   Java source line #352	-> byte code offset #123
/*     */     //   Java source line #355	-> byte code offset #130
/*     */     //   Java source line #356	-> byte code offset #142
/*     */     //   Java source line #357	-> byte code offset #159
/*     */     //   Java source line #358	-> byte code offset #166
/*     */     //   Java source line #359	-> byte code offset #180
/*     */     //   Java source line #360	-> byte code offset #194
/*     */     //   Java source line #361	-> byte code offset #197
/*     */     //   Java source line #363	-> byte code offset #201
/*     */     //   Java source line #364	-> byte code offset #211
/*     */     //   Java source line #365	-> byte code offset #228
/*     */     //   Java source line #363	-> byte code offset #238
/*     */     //   Java source line #364	-> byte code offset #250
/*     */     //   Java source line #365	-> byte code offset #267
/*     */     // Local variable table:
/*     */     //   start	length	slot	name	signature
/*     */     //   0	277	0	is	InputStream
/*     */     //   0	277	1	filename	String
/*     */     //   0	277	2	contentType	String
/*     */     //   0	277	3	accountId	String
/*     */     //   0	277	4	limit	long
/*     */     //   1	267	6	fi	FileItem
/*     */     //   4	237	7	success	boolean
/*     */     //   11	94	8	upload	ServletFileUpload
/*     */     //   18	42	9	sizeMax	long
/*     */     //   66	13	11	size	long
/*     */     //   140	58	13	up	Upload
/*     */     //   186	6	15	localObject1	Object
/*     */     //   238	37	16	localObject2	Object
/*     */     // Exception table:
/*     */     //   from	to	target	type
/*     */     //   166	183	186	finally
/*     */     //   186	191	186	finally
/*     */     //   6	201	238	finally
/*     */     //   238	240	238	finally
/*     */   }
/*     */   
/*     */   public static Upload saveUpload(InputStream is, String filename, String contentType, String accountId)
/*     */     throws ServiceException, IOException
/*     */   {
/* 371 */     return saveUpload(is, filename, contentType, accountId, false);
/*     */   }
/*     */   
/*     */   static File getStoreLocation(FileItem fi) {
/* 375 */     if ((fi.isInMemory()) || (!(fi instanceof DiskFileItem))) {
/* 376 */       return null;
/*     */     }
/* 378 */     return ((DiskFileItem)fi).getStoreLocation();
/*     */   }
/*     */   
/*     */   public static void deleteUploads(Collection<Upload> uploads) {
/* 382 */     if ((uploads != null) && (!uploads.isEmpty())) {
/* 383 */       for (Upload up : uploads)
/* 384 */         deleteUpload(up);
/*     */     }
/*     */   }
/*     */   
/*     */   public static void deleteUpload(Upload upload) {
/* 389 */     if (upload == null)
/*     */       return;
/*     */     Upload up;
/* 392 */     synchronized (mPending) {
/* 393 */       mLog.debug("deleteUpload(): removing %s", new Object[] { upload });
/* 394 */       up = (Upload)mPending.remove(upload.uuid);
/* 395 */       if (up != null) {
/* 396 */         up.markDeleted();
/*     */       }
/*     */     }
/* 399 */     if (up == upload) {
/* 400 */       up.purge();
/*     */     }
/*     */   }
/*     */   
/*     */   protected static String getUploadDir() {
/* 405 */     if (sUploadDir == null) {
/* 406 */       sUploadDir = LC.zimbra_tmp_directory.value() + "/upload";
/*     */     }
/* 408 */     return sUploadDir;
/*     */   }
/*     */   
/*     */   private static class TempFileFilter implements FileFilter {
/* 412 */     private final long mNow = System.currentTimeMillis();
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     public boolean accept(File pathname)
/*     */     {
/* 423 */       if (pathname == null)
/* 424 */         return false;
/* 425 */       String name = pathname.getName();
/*     */       
/* 427 */       return (name.startsWith("upload_")) && (name.endsWith(".tmp")) && (this.mNow - pathname.lastModified() > 900000L);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void cleanupLeftoverTempFiles() {
/* 432 */     File[] files = new File(getUploadDir()).listFiles(new TempFileFilter());
/* 433 */     if ((files == null) || (files.length < 1)) {
/* 434 */       return;
/*     */     }
/* 436 */     mLog.info("deleting %d temporary upload files left over from last time", new Object[] { Integer.valueOf(files.length) });
/* 437 */     for (int i = 0; i < files.length; i++) {
/* 438 */       String path = files[i].getAbsolutePath();
/* 439 */       if (files[i].delete()) {
/* 440 */         mLog.info("deleted leftover upload file %s", new Object[] { path });
/*     */       } else {
/* 442 */         mLog.error("unable to delete leftover upload file %s", new Object[] { path });
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
/*     */   {
/* 449 */     ZimbraLog.clearContext();
/* 450 */     addRemoteIpToLoggingContext(req);
/*     */     
/* 452 */     String fmt = req.getParameter("fmt");
/*     */     
/* 454 */     ZimbraLog.addUserAgentToContext(req.getHeader("User-Agent"));
/*     */     
/*     */ 
/* 457 */     boolean isAdminRequest = false;
/*     */     try {
/* 459 */       isAdminRequest = isAdminRequest(req);
/*     */     } catch (ServiceException e) {
/* 461 */       drainRequestStream(req);
/* 462 */       throw new ServletException(e);
/*     */     }
/*     */     
/* 465 */     AuthToken at = isAdminRequest ? getAdminAuthTokenFromCookie(req, resp, true) : getAuthTokenFromCookie(req, resp, true);
/* 466 */     if (at == null) {
/* 467 */       mLog.info("Auth token not present.  Returning %d response.", new Object[] { Integer.valueOf(401) });
/* 468 */       drainRequestStream(req);
/* 469 */       sendResponse(resp, 401, fmt, null, null, null);
/* 470 */       return;
/*     */     }
/*     */     
/* 473 */     boolean doCsrfCheck = false;
/* 474 */     boolean csrfCheckComplete = false;
/* 475 */     if (req.getAttribute("CsrfTokenCheck") != null) {
/* 476 */       doCsrfCheck = ((Boolean)req.getAttribute("CsrfTokenCheck")).booleanValue();
/*     */     }
/*     */     
/* 479 */     if (doCsrfCheck) {
/* 480 */       String csrfToken = req.getHeader("X-Zimbra-Csrf-Token");
/*     */       
/*     */ 
/* 483 */       if (!StringUtil.isNullOrEmpty(csrfToken)) {
/* 484 */         if (!CsrfUtil.isValidCsrfToken(csrfToken, at))
/*     */         {
/* 486 */           drainRequestStream(req);
/* 487 */           mLog.info("CSRF token validation failed for account: %s, Auth token is CSRF enabled: %s. CSRF token is: %s", new Object[] { at, Boolean.valueOf(at.isCsrfTokenEnabled()), csrfToken });
/*     */           
/*     */ 
/* 490 */           sendResponse(resp, 401, fmt, null, null, null);
/* 491 */           return;
/*     */         }
/* 493 */         csrfCheckComplete = true;
/*     */       }
/* 495 */       else if (at.isCsrfTokenEnabled()) {
/* 496 */         csrfCheckComplete = false;
/* 497 */         mLog.debug("CSRF token was not found in the header. Auth token is %s, it is CSRF enabled:  %s, will check if sent in form field.", new Object[] { at, Boolean.valueOf(at.isCsrfTokenEnabled()) });
/*     */       }
/*     */     }
/*     */     else
/*     */     {
/* 502 */       csrfCheckComplete = true;
/*     */     }
/*     */     
/*     */     try
/*     */     {
/* 507 */       Provisioning prov = Provisioning.getInstance();
/* 508 */       Account acct = AuthProvider.validateAuthToken(prov, at, true);
/* 509 */       if (!isAdminRequest)
/*     */       {
/* 511 */         if (Provisioning.onLocalServer(acct)) {
/* 512 */           Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(acct, false);
/* 513 */           if (mbox != null) {
/* 514 */             ZimbraLog.addMboxToContext(mbox.getId());
/*     */           }
/*     */         }
/*     */       }
/*     */       
/* 519 */       boolean limitByFileUploadMaxSize = req.getParameter("lbfums") != null;
/*     */       
/*     */ 
/* 522 */       if (ServletFileUpload.isMultipartContent(req)) {
/* 523 */         handleMultipartUpload(req, resp, fmt, acct, limitByFileUploadMaxSize, at, csrfCheckComplete);
/*     */       }
/* 525 */       else if (!csrfCheckComplete) {
/* 526 */         drainRequestStream(req);
/* 527 */         mLog.info("CSRF token validation failed for account: %s.No csrf token recd.", new Object[] { acct });
/* 528 */         sendResponse(resp, 401, fmt, null, null, null);
/*     */       } else {
/* 530 */         handlePlainUpload(req, resp, fmt, acct, limitByFileUploadMaxSize);
/*     */       }
/*     */     }
/*     */     catch (ServiceException e) {
/* 534 */       mLog.info("File upload failed", e);
/* 535 */       drainRequestStream(req);
/* 536 */       returnError(resp, e);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   List<Upload> handleMultipartUpload(HttpServletRequest req, HttpServletResponse resp, String fmt, Account acct, boolean limitByFileUploadMaxSize, AuthToken at, boolean csrfCheckComplete)
/*     */     throws IOException, ServiceException
/*     */   {
/* 544 */     List<FileItem> items = null;
/* 545 */     String reqId = null;
/*     */     
/* 547 */     ServletFileUpload upload = getUploader2(limitByFileUploadMaxSize);
/*     */     try {
/* 549 */       items = upload.parseRequest(req);
/*     */       
/* 551 */       if ((!csrfCheckComplete) && (!CsrfUtil.checkCsrfInMultipartFileUpload(items, at))) {
/* 552 */         drainRequestStream(req);
/* 553 */         mLog.info("CSRF token validation failed for account: %s, Auth token is CSRF enabled", new Object[] { acct.getName() });
/* 554 */         sendResponse(resp, 401, fmt, null, null, items);
/* 555 */         return Collections.emptyList();
/*     */       }
/*     */     }
/*     */     catch (FileUploadBase.SizeLimitExceededException e) {
/* 559 */       mLog.info("Exceeded maximum upload size of " + upload.getSizeMax() + " bytes: " + e);
/* 560 */       drainRequestStream(req);
/* 561 */       sendResponse(resp, 413, fmt, reqId, null, items);
/* 562 */       return Collections.emptyList();
/*     */     }
/*     */     catch (FileUploadBase.InvalidContentTypeException e) {
/* 565 */       mLog.info("File upload failed", e);
/* 566 */       drainRequestStream(req);
/* 567 */       sendResponse(resp, 415, fmt, reqId, null, items);
/* 568 */       return Collections.emptyList();
/*     */     }
/*     */     catch (FileUploadException e) {
/* 571 */       mLog.info("File upload failed", e);
/* 572 */       drainRequestStream(req);
/* 573 */       sendResponse(resp, 500, fmt, reqId, null, items);
/* 574 */       return Collections.emptyList();
/*     */     }
/*     */     
/* 577 */     String charset = "utf-8";
/* 578 */     LinkedList<String> names = new LinkedList();
/* 579 */     HashMap<FileItem, String> filenames = new HashMap();
/* 580 */     Iterator<FileItem> it; if (items != null) {
/* 581 */       for (it = items.iterator(); it.hasNext();) {
/* 582 */         FileItem fi = (FileItem)it.next();
/* 583 */         if (fi != null)
/*     */         {
/*     */ 
/* 586 */           if (fi.isFormField()) {
/* 587 */             if (fi.getFieldName().equals("requestId"))
/*     */             {
/* 589 */               reqId = fi.getString();
/* 590 */             } else if ((fi.getFieldName().equals("_charset_")) && (!fi.getString().equals("")))
/*     */             {
/* 592 */               charset = fi.getString();
/* 593 */             } else if (fi.getFieldName().startsWith("filename"))
/*     */             {
/* 595 */               names.clear();
/* 596 */               String value = fi.getString(charset);
/* 597 */               if (!Strings.isNullOrEmpty(value)) {
/* 598 */                 for (String name : value.split("\n")) {
/* 599 */                   names.add(name.trim());
/*     */                 }
/*     */               }
/*     */             }
/*     */             
/* 604 */             it.remove();
/*     */           }
/* 606 */           else if ((fi.getName() == null) || (fi.getName().trim().equals(""))) {
/* 607 */             it.remove();
/*     */           } else {
/* 609 */             filenames.put(fi, names.isEmpty() ? null : (String)names.remove());
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 616 */     if ((reqId != null) && (reqId.length() != 0) && 
/* 617 */       (!this.ALLOWED_REQUESTID_CHARS.matcher(reqId).matches())) {
/* 618 */       mLog.info("Rejecting upload with invalid chars in reqId: %s", new Object[] { reqId });
/* 619 */       sendResponse(resp, 400, fmt, null, null, items);
/* 620 */       return Collections.emptyList();
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 625 */     if ((items == null) || (items.isEmpty())) {
/* 626 */       mLog.info("No data in upload for reqId: %s", new Object[] { reqId });
/* 627 */       sendResponse(resp, 204, fmt, reqId, null, items);
/* 628 */       return Collections.emptyList();
/*     */     }
/*     */     
/*     */ 
/* 632 */     List<Upload> uploads = new ArrayList(items.size());
/* 633 */     for (FileItem fi : items) {
/* 634 */       String name = (String)filenames.get(fi);
/* 635 */       if ((name == null) || (name.trim().equals("")))
/* 636 */         name = fi.getName();
/* 637 */       Upload up = new Upload(acct.getId(), fi, name);
/*     */       
/* 639 */       mLog.info("Received multipart: %s", new Object[] { up });
/* 640 */       synchronized (mPending) {
/* 641 */         mPending.put(up.uuid, up);
/*     */       }
/* 643 */       uploads.add(up);
/*     */     }
/*     */     
/* 646 */     sendResponse(resp, 200, fmt, reqId, uploads, items);
/* 647 */     return uploads;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   List<Upload> handlePlainUpload(HttpServletRequest req, HttpServletResponse resp, String fmt, Account acct, boolean limitByFileUploadMaxSize)
/*     */     throws IOException, ServiceException
/*     */   {
/* 665 */     ContentType ctype = new ContentType(req.getContentType());
/* 666 */     String contentType = ctype.getContentType();String filename = ctype.getParameter("name");
/* 667 */     if (filename == null) {
/* 668 */       filename = new ContentDisposition(req.getHeader("Content-Disposition")).getParameter("filename");
/*     */     }
/*     */     
/* 671 */     if ((filename == null) || (filename.trim().equals(""))) {
/* 672 */       mLog.info("Rejecting upload with no name.");
/* 673 */       drainRequestStream(req);
/* 674 */       sendResponse(resp, 204, fmt, null, null, null);
/* 675 */       return Collections.emptyList();
/*     */     }
/*     */     
/*     */ 
/* 679 */     filename = StringEscapeUtils.unescapeHtml(filename);
/*     */     
/*     */ 
/* 682 */     ServletFileUpload upload = getUploader2(limitByFileUploadMaxSize);
/* 683 */     FileItem fi = upload.getFileItemFactory().createItem("upload", contentType, false, filename);
/*     */     try
/*     */     {
/* 686 */       long size = ByteUtil.copy(req.getInputStream(), false, fi.getOutputStream(), true, upload.getSizeMax() * 3L);
/* 687 */       if ((upload.getSizeMax() >= 0L) && (size > upload.getSizeMax())) {
/* 688 */         mLog.debug("handlePlainUpload(): deleting %s", new Object[] { fi });
/* 689 */         fi.delete();
/* 690 */         mLog.info("Exceeded maximum upload size of " + upload.getSizeMax() + " bytes: " + acct.getId());
/* 691 */         drainRequestStream(req);
/* 692 */         sendResponse(resp, 413, fmt, null, null, null);
/* 693 */         return Collections.emptyList();
/*     */       }
/*     */     } catch (IOException ioe) {
/* 696 */       mLog.warn("Unable to store upload.  Deleting %s", fi, ioe);
/* 697 */       fi.delete();
/* 698 */       drainRequestStream(req);
/* 699 */       sendResponse(resp, 500, fmt, null, null, null);
/* 700 */       return Collections.emptyList();
/*     */     }
/* 702 */     List<FileItem> items = new ArrayList(1);
/* 703 */     items.add(fi);
/*     */     
/* 705 */     Upload up = new Upload(acct.getId(), fi, filename);
/* 706 */     mLog.info("Received plain: %s", new Object[] { up });
/* 707 */     synchronized (mPending) {
/* 708 */       mPending.put(up.uuid, up);
/*     */     }
/*     */     
/* 711 */     List<Upload> uploads = Arrays.asList(new Upload[] { up });
/* 712 */     sendResponse(resp, 200, fmt, null, uploads, items);
/* 713 */     return uploads;
/*     */   }
/*     */   
/*     */   public static void sendResponse(HttpServletResponse resp, int status, String fmt, String reqId, List<Upload> uploads, List<FileItem> items) throws IOException
/*     */   {
/* 718 */     boolean raw = false;boolean extended = false;
/* 719 */     if ((fmt != null) && (!fmt.trim().equals("")))
/*     */     {
/* 721 */       for (String foption : fmt.toLowerCase().split(",")) {
/* 722 */         raw |= "raw".equals(foption);
/* 723 */         extended |= "extended".equals(foption);
/*     */       }
/*     */     }
/*     */     
/* 727 */     StringBuffer results = new StringBuffer();
/* 728 */     results.append(status).append(",'").append(reqId != null ? StringUtil.jsEncode(reqId) : "null").append('\'');
/* 729 */     if (status == 200) {
/* 730 */       boolean first = true;
/* 731 */       if (extended)
/*     */       {
/* 733 */         results.append(",[");
/* 734 */         for (Upload up : uploads) {
/* 735 */           Element.JSONElement elt = new Element.JSONElement("ignored");
/* 736 */           elt.addAttribute("aid", up.uuid);
/* 737 */           elt.addAttribute("ct", up.getContentType());
/* 738 */           elt.addAttribute("filename", up.name);
/* 739 */           elt.addAttribute("s", up.getSize());
/* 740 */           results.append(first ? "" : ",").append(elt.toString());
/* 741 */           first = false;
/*     */         }
/* 743 */         results.append(']');
/*     */       }
/*     */       else {
/* 746 */         results.append(",'");
/* 747 */         for (Upload up : uploads) {
/* 748 */           results.append(first ? "" : ",").append(up.uuid);
/* 749 */           first = false;
/*     */         }
/* 751 */         results.append('\'');
/*     */       }
/*     */     }
/*     */     
/* 755 */     resp.setContentType("text/html; charset=utf-8");
/* 756 */     PrintWriter out = resp.getWriter();
/*     */     
/* 758 */     if (raw) {
/* 759 */       out.println(results);
/*     */     } else {
/* 761 */       out.println("<html><head><script language='javascript'>\nfunction doit() { window.parent._uploadManager.loaded(" + results + "); }\n</script>" + "</head><body onload='doit()'></body></html>\n");
/*     */     }
/*     */     
/*     */ 
/* 765 */     out.close();
/*     */     
/*     */ 
/* 768 */     if ((status != 200) && (items != null) && (items.size() > 0)) {
/* 769 */       for (FileItem fi : items) {
/* 770 */         mLog.debug("sendResponse(): deleting %s", new Object[] { fi });
/* 771 */         fi.delete();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public static void drainRequestStream(HttpServletRequest req)
/*     */   {
/*     */     try
/*     */     {
/* 782 */       InputStream in = req.getInputStream();
/* 783 */       byte[] buf = new byte['Ѐ'];
/* 784 */       int numRead = 0;
/* 785 */       int totalRead = 0;
/* 786 */       mLog.debug("Draining request input stream");
/* 787 */       while ((numRead = in.read(buf)) >= 0) {
/* 788 */         totalRead += numRead;
/*     */       }
/* 790 */       mLog.debug("Drained %d bytes", new Object[] { Integer.valueOf(totalRead) });
/*     */     } catch (IOException e) {
/* 792 */       mLog.info("Ignoring error that occurred while reading the end of the client request: " + e);
/*     */     }
/*     */   }
/*     */   
/*     */   private static long getFileUploadMaxSize(boolean limitByFileUploadMaxSize)
/*     */   {
/* 798 */     long maxSize = 10485760L;
/*     */     try {
/* 800 */       if (limitByFileUploadMaxSize) {
/* 801 */         maxSize = Provisioning.getInstance().getLocalServer().getLongAttr("zimbraFileUploadMaxSize", 10485760L);
/*     */       }
/*     */       else {
/* 804 */         maxSize = Provisioning.getInstance().getConfig().getLongAttr("zimbraMtaMaxMessageSize", 10485760L);
/*     */         
/* 806 */         if (maxSize == 0L)
/*     */         {
/*     */ 
/*     */ 
/* 810 */           maxSize = -1L;
/*     */         }
/*     */       }
/*     */     } catch (ServiceException e) {
/* 814 */       mLog.error("Unable to read " + (limitByFileUploadMaxSize ? "zimbraFileUploadMaxSize" : "zimbraMtaMaxMessageSize") + " attribute", e);
/*     */     }
/*     */     
/*     */ 
/* 818 */     return maxSize;
/*     */   }
/*     */   
/*     */   public static ServletFileUpload getUploader2(boolean limitByFileUploadMaxSize) {
/* 822 */     return getUploader(getFileUploadMaxSize(limitByFileUploadMaxSize));
/*     */   }
/*     */   
/*     */   public static ServletFileUpload getUploader(long maxSize) {
/* 826 */     DiskFileItemFactory dfif = new DiskFileItemFactory();
/* 827 */     dfif.setSizeThreshold(32768);
/* 828 */     dfif.setRepository(new File(getUploadDir()));
/* 829 */     ServletFileUpload upload = new ServletFileUpload(dfif);
/* 830 */     upload.setSizeMax(maxSize);
/* 831 */     upload.setHeaderEncoding("utf-8");
/* 832 */     return upload;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void init()
/*     */     throws ServletException
/*     */   {
/* 842 */     String name = getServletName();
/* 843 */     mLog.info("Servlet %s starting up", new Object[] { name });
/* 844 */     super.init();
/*     */     
/* 846 */     File tempDir = new File(getUploadDir());
/* 847 */     if ((!tempDir.exists()) && 
/* 848 */       (!tempDir.mkdirs())) {
/* 849 */       String msg = "Unable to create temporary upload directory " + tempDir;
/* 850 */       mLog.error(msg);
/* 851 */       throw new ServletException(msg);
/*     */     }
/*     */     
/* 854 */     cleanupLeftoverTempFiles();
/*     */     
/* 856 */     Zimbra.sTimer.schedule(new MapReaperTask(), 60000L, 60000L);
/*     */   }
/*     */   
/*     */   public void destroy()
/*     */   {
/* 861 */     String name = getServletName();
/* 862 */     mLog.info("Servlet %s shutting down", new Object[] { name });
/* 863 */     super.destroy();
/*     */   }
/*     */   
/*     */   private final class MapReaperTask extends TimerTask
/*     */   {
/*     */     MapReaperTask() {}
/*     */     
/*     */     public void run() {
/*     */       try {
/* 872 */         ArrayList<FileUploadServlet.Upload> reaped = new ArrayList();
/*     */         int sizeBefore;
/*     */         int sizeAfter;
/* 875 */         synchronized (FileUploadServlet.mPending) {
/* 876 */           sizeBefore = FileUploadServlet.mPending.size();
/* 877 */           long cutoffTime = System.currentTimeMillis() - 900000L;
/* 878 */           for (Iterator<FileUploadServlet.Upload> it = FileUploadServlet.mPending.values().iterator(); it.hasNext();) {
/* 879 */             FileUploadServlet.Upload up = (FileUploadServlet.Upload)it.next();
/* 880 */             if (!up.accessedAfter(cutoffTime)) {
/* 881 */               FileUploadServlet.mLog.debug("Purging cached upload: %s", new Object[] { up });
/* 882 */               it.remove();
/* 883 */               reaped.add(up);
/* 884 */               up.markDeleted();
/* 885 */               assert (FileUploadServlet.mPending.get(up.uuid) == null);
/*     */             }
/*     */           }
/* 888 */           sizeAfter = FileUploadServlet.mPending.size();
/*     */         }
/*     */         
/* 891 */         int removed = sizeBefore - sizeAfter;
/* 892 */         if (removed > 0) {
/* 893 */           FileUploadServlet.mLog.info("Removed %d expired file uploads; %d pending file uploads", new Object[] { Integer.valueOf(removed), Integer.valueOf(sizeAfter) });
/* 894 */         } else if (sizeAfter > 0) {
/* 895 */           FileUploadServlet.mLog.info("%d pending file uploads", new Object[] { Integer.valueOf(sizeAfter) });
/*     */         }
/*     */         
/* 898 */         for (FileUploadServlet.Upload up : reaped) {
/* 899 */           up.purge();
/*     */         }
/*     */       } catch (Throwable e) {
/* 902 */         if ((e instanceof OutOfMemoryError)) {
/* 903 */           Zimbra.halt("Caught out of memory error", e);
/*     */         }
/* 905 */         ZimbraLog.system.warn("Caught exception in FileUploadServlet timer", e);
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/FileUploadServlet.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */